package top.kaoshanji.ch01.collecting;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 代码清单 ch01-05：收集到映射表中的示例(1.9/10节)
 * author kaoshanji
 * ^_^
 * create time 2024/12/5 16:49
 */
public class CollectingIntoMaps {

    private static final Logger logger = LogManager.getLogger(CollectingIntoMaps.class);

    public static void main(String[] args) {
        logger.info("...代码清单 ch01-05：收集到映射表中的示例(1.9/10节)...");

        logger.info("...值是单个元素...");

        // 【例1】 键：id、值：name
        Map<Integer, String> idToName = people().collect(Collectors.toMap(Person::getId, Person::getName));
        System.out.println("idToName: " + idToName);

        // 【例2】 键：id、值：实体对象
        Map<Integer, Person> idToPerson = people().collect(Collectors.toMap(Person::getId, Function.identity()));
        System.out.println("idToPerson: " + idToPerson.getClass().getName() + idToPerson);

        // 【例3】 键：id、值：实体对象..多个值有相同的键就冲突了，将抛出异常，不过，可以覆盖这种行为
        idToPerson = people().collect(Collectors.toMap(Person::getId, Function.identity(),
                (existingValue, newValue) -> {throw new IllegalStateException();}, TreeMap::new));
        System.out.println("idToPerson: " + idToPerson.getClass().getName() + idToPerson);


        Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());

        // 【例4】 键：Locale中的名字、值：本地化的名字 多个值有相同的键就冲突了..这里选择已有的值
        Map<String, String> languageNames = locales.collect(Collectors.toMap(Locale::getDisplayLanguage, l -> l.getDisplayLanguage(l),
                (existingValue, newValue) -> existingValue));
        System.out.println("languageNames: " + languageNames);

        logger.info("...值是多个元素...");
        // 【例5】 键：国家地区、值：所有的语言集....这就写的甚是纠结了啊...
        locales = Stream.of(Locale.getAvailableLocales());
        Map<String, Set<String>> countryLanguageSets = locales.collect(Collectors.toMap(Locale::getDisplayCountry, l -> Set.of(l.getDisplayLanguage()),
                (a, b) -> {
                    Set<String> union = new HashSet<>(a);
                    union.addAll(b);
                    return union;
                }));
        System.out.println("countryLanguageSets: " + countryLanguageSets);

        // 【【例6】 例5的改进版本
        // 这是 1.10 节示例
        locales = Stream.of(Locale.getAvailableLocales()); // 流需要再新建一遍
        Map<String, List<Locale>> countryToLocales = locales.collect(Collectors.groupingBy(Locale::getCountry));
        System.out.println("countryToLocales: " + countryToLocales.get("CH"));

    }

    public static Stream<Person> people() {
        return Stream.of(new Person(1001, "Peter"), new Person(1002, "Paul"), new Person(1003, "Mary"));
    }

}
